home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mntlib43 / mntlib / ldexp.cpp < prev    next >
C/C++ Source or Header  |  1993-06-17  |  6KB  |  226 lines

  1.     .text
  2.     .globl _ldexp
  3.     .globl __infinitydf
  4.     .even
  5. #ifdef    ERROR_CHECK
  6. #include "errbase.h"
  7. _Overflow:
  8.     .ascii "ldexp: OVERFLOW\12\15\0"
  9. # if defined(__M68881__) || defined(sfp004)
  10. _Domain:
  11.     .ascii "ldexp: NAN\12\15\0"
  12.     .even
  13. double_max:
  14.     .long    0x7fee42d1
  15.     .long    0x30273b76
  16. double_min:
  17.     .long    0xffee42d1
  18.     .long    0x30273b76
  19. NaN:
  20.     .long    0x7fffffff
  21.     .long    0xffffffff
  22. p_Inf:
  23.     .long    0x7ff00000
  24.     .long    0x00000000
  25. m_Inf:
  26.     .long    0xfff00000
  27.     .long    0x00000000
  28. # endif
  29.     .even
  30. #endif    ERROR_CHECK
  31. _ldexp:
  32. #if !defined (__M68881__) && !defined (sfp004)
  33.  
  34.  | add exponent to floating point number
  35.  | C Interface
  36.  | double ldexp(double value, unsigned int exp);
  37.  | returns value * 2**exp
  38.  | (int is 16 bits if -mshort, 32 bits if !-mshort)
  39.  |-----------------------------------------------------------------------------
  40.  | ported to 68000 by Kai-Uwe Bloem, 12/89
  41.  |  #1  original author: Peter S. Housel 9/21/88,01/17/89,03/19/89,5/24/89
  42.  |  #2    added support for denormalized numbers            -kub-, 01/90
  43.  |  #3  ported to gcc  ++jrb  04/90
  44.  |  #4  handle exponent overflow when ints are 32 bits        -kub-, 04/90
  45.  |  #5  make returned zero signed                  mj,  05/93
  46.  |-----------------------------------------------------------------------------
  47.  
  48.     lea    sp@(4),a1
  49.     moveml    d2-d7,sp@-    | save d2-d7
  50.  
  51.     movew    a1@,d0        | extract value.exp
  52.     movew    d0,d2        | extract value.sign
  53.     bclr    #15,d0        | kill sign bit
  54.     lsrw    #4,d0
  55.  
  56.     moveq    #0x0f,d3    | remove exponent from value.mantissa
  57.     andb    d2,d3        | four upper bits of value in d3
  58.     bset    #4,d3        | implied leading 1
  59.     tstw    d0        | check for zero exponent
  60.     bne    1f
  61.     addqw    #1,d0
  62.     bclr    #4,d3        | nah, we do not need stinkin leadin 1
  63. 1:    movew    d3,a1@        | save results of our efforts
  64. #ifdef __MSHORT__
  65.     addw    a1@(8),d0    | add in exponent
  66.     extl    d0
  67. #else
  68.     extl    d0
  69.     addl    a1@(8),d0    | add in exponent
  70. #endif
  71.     cmpl    #-53,d0        | hmm. works only if 1 in implied position...
  72.     ble    retz        | range error - underflow
  73.     cmpl    #0x7ff,d0
  74.     bge    rangerr        | range error - overflow
  75.  
  76.     clrw    d1        | zero rounding bits
  77.     moveml    a1@,d4-d5    | value into d4,d5
  78.     jmp    norm_df        | norm_df will pop d2-d7 and rts
  79.  
  80. retz:
  81.     moveq    #0,d0        | zero return value
  82.     movel    d0,d1
  83.     lslw    #1,d2        | transfer argument sign
  84.     roxrl    #1,d0
  85.     jra    L0
  86.  
  87. rangerr:
  88.  
  89. #ifdef ERROR_CHECK
  90.     moveq    #Erange,d0
  91.     Emove    d0,Errno
  92.     pea    pc@(_Overflow)    | for printf
  93.     pea    Stderr        |
  94.     jbsr    _fprintf    |
  95.     addql    #8,a7        |
  96. #endif ERROR_CHECK
  97.  
  98.     moveml    __infinitydf,d0-d1 | return HUGE_VAL (same as in <math.h>)
  99.     tstw    d2
  100.     bge    L0
  101.     bset    #31,d0
  102. L0:
  103.     moveml    sp@+,d2-d7    | pop saved reggies
  104.     rts
  105.  
  106. #else    __M68881__ || sfp004
  107. #ifdef    __M68881__
  108. |#######################################################################
  109. |
  110. |# add exponent to floating point number
  111. |# C Interface
  112. |# double ldexp(double value, unsigned int exp);
  113. |# returns value * 2**exp
  114. |# (int is 16 bits if -mshort, 32 bits if !-mshort)
  115. |# performed entirely on the 68881 to avoid overfow as good as possible
  116. |##############################################################################
  117. |# hacked for the 68881 by Michael Ritzert, 5.10.90
  118. |##############################################################################
  119. |# ported fromt sfp004 to real coprocessor, mjr, August 1991
  120. |##############################################################################
  121.  
  122. #ifdef __MSHORT__
  123.     movew    a7@(12),d0        | get exponent
  124.     extl    d0
  125. #else
  126.     movel    a7@(12),d0        | get exponent
  127. #endif
  128.     fgetexpd a7@(4),fp1        | extract exponent of 1st arg
  129.     fmovel    fp1,d1            | d1 serves as accumulator
  130.     addl    d0,d1            | sum of exp_s of both args
  131.  
  132.     ftwotoxl d0,fp0            | ftwotox to fp0 (as long int!)
  133.     fmuld    a7@(4),fp0        | fmul value,fp0
  134.     fmoved    fp0,a7@-        | get double from fp0
  135.     moveml    a7@+,d0-d1
  136.  
  137. #endif  __M68881__
  138. #ifdef    sfp004
  139.  
  140. | add exponent to floating point number
  141. | C Interface
  142. | double ldexp(double value, unsigned int exp);
  143. | returns value * 2**exp
  144. | (int is 16 bits if -mshort, 32 bits if !-mshort)
  145. | performed entirely on the 68881 to avoid overfow as good as possible
  146. |
  147. | hacked for the 68881 by Michael Ritzert, 5.10.90
  148. |
  149.  
  150. | addresses of the 68881 data port. This choice is fastest when much data is
  151. | transferred between the two processors.
  152.  
  153. comm =     -6    |    fpu command reg
  154. resp =    -16    |    fpu response reg
  155. zahl =      0    |    fpu data reg
  156.  
  157. | waiting loop ...
  158. |
  159. | wait:
  160. | ww:    cmpiw    #0x8900,a1@(resp)
  161. |     beq    ww
  162. | is coded directly by
  163. |    .byte    0x0c,0x69,0x89,0x00,0xff,0xf0,0x67,0xf8 (a1)
  164. |    or
  165. |    .long    0x0c6889000, 0x000067f8            (a0)
  166.  
  167. #ifdef __MSHORT__
  168.     movew    sp@(12),d0        | get exponent
  169.     extl    d0
  170. #else
  171.     movel    sp@(12),d0        | get exponent
  172. #endif
  173.     lea    0xfffffa50:w,a0        | fpu address
  174.     movew    #0x549e,a0@(comm)    | fgetexpd sp@(4),fp1
  175.     cmpiw    #0x8900,a0@(resp)
  176.     movel    sp@(4),a0@
  177.     movel    sp@(8),a0@
  178.     movew    #0x6080,a0@(comm)    | fmovel fp1,d1
  179.     .long    0x0c688900, 0xfff067f8
  180.     movel    a0@,d1
  181.     addl    d0,d1
  182.     movew    #0x4011,a0@(comm)    | ftwotoxl d0,fp0
  183.     .long    0x0c688900, 0xfff067f8
  184.     movel    d0,a0@
  185.     movew    #0x5423,a0@(comm)    | fmuld sp@(4),fp0
  186.     .long    0x0c688900, 0xfff067f8
  187.     movel    sp@(4),a0@
  188.     movel    sp@(8),a0@
  189.     movew    #0x7400,a0@(comm)    | fmoved fp0,d0/d1
  190.     .long    0x0c688900, 0xfff067f8
  191.     movel    a0@,d0
  192.     movel    a0@,d1
  193. #endif    sfp004
  194.  
  195. #ifdef    ERROR_CHECK
  196.     lea    double_max,a0    |
  197.     swap    d0        | exponent into lower word
  198.     cmpw    a0@(16),d0    | == NaN ?
  199.     beq    error_nan    |
  200.     cmpw    a0@(24),d0    | == + Infinity ?
  201.     beq    error_plus    |
  202.     swap    d0        | result ok,
  203.     rts            | restore d0
  204. error_plus:
  205.     swap    d0
  206.     moveml    d0-d1,a7@-    | print error message
  207.     moveq    #Erange,d0    | Overflow: errno = ERANGE
  208.     Emove    d0,Errno
  209.     pea    pc@(_Domain)    | for printf
  210.     bra    error_exit    |
  211. error_nan:
  212.     moveq    #Edom,d0    | NAN => errno = EDOM
  213.     Emove    d0,Errno
  214.     moveml    a0@(24),d0-d1    | result = +inf
  215.     moveml    d0-d1,a7@-    | print error message
  216.     pea    pc@(_Overflow)    | for printf
  217. error_exit:
  218.     pea    Stderr        |
  219.     jbsr    _fprintf    |
  220.     addql    #8,a7        |
  221.     moveml    a7@+,d0-d1
  222. #endif    ERROR_CHECK
  223.     rts
  224.  
  225. #endif    /* !__M68881__ && !sfp004    */
  226.